home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
PROGRAMM
/
CC_C
/
0151.ZIP
/
SCAV23X.ASM
< prev
next >
Wrap
Assembly Source File
|
1985-07-12
|
10KB
|
461 lines
title scavenge Copyright (c) T. Jennings 1983
;
;****************************************
;* *
;* SCAVENGE *
;* *
;* Mark bad blocks on MSDOS *
;* as allocated in the FAT. *
;* *
;* T. Jennings 12 July 85 *
;* created 15 Sept. 82 *
;* *
;****************************************
;
;Reads all sectors in logical MSDOS blocks
;and marks the file allocation tables such
;that the blocks are permanently allocated
;where CHKDSK will not deallocate them.
;
;
;This version works on any 2.xx or 3.xx MSDOS,
;PCDOS, on any media type, fixed or removable.
;One (major) limitation: it will not map out
;blocks that are already allocated to a file;
;it will say "block used", but won't tell you
;which file it is in.
;
;If SCAVENGE finds any bad blocks, it will ask
;you whether or not you want the disk updated.
;You can safely run it just to see if the disk
;is OK.
;
;MASM, LINK, then EXE2BIN this to make a COM
;file. It will not run as an EXE file. NOTE:
;LINK will give you a 'Warning: no STACK
;segment' error: ignore it.
;
cr equ 0dh
lf equ 0ah
page
cgroup group code
code segment byte public 'code'
assume cs:cgroup,ds:cgroup,ss:cgroup
;
;MSDOS page 0 stuff.
;
org 5ch
tfcb label byte
org 80h
tbuff label byte
org 100h
scavenge:
jmp start
;
;Disk parameters:
;
blkcnt dw (0) ;blocks this disk
blksize dw (0) ;sectors per block
secsize dw (0) ;phys. sector size
badcnt dw (0) ;# bad blocks found
newbad dw (0) ;new bad ones
block dw (0) ;current block
sector dw (0) ;sector to read
disk db (0) ;selected disk
curdsk db (0) ;current disk.
fatsec dw (0) ;1st FAT sector,
fatcnt dw (0) ;FAT sec count.
fat16 db (0) ;1 == 16 bit FAT
blkdsp db (0) ;display counter
dw 128 dup (0)
stack dw (0) ;what else
page
;
;Say who we are, describe the disk we are
;about to fix, ask to continue or abort.
;
start: mov ax,cs
mov ds,ax
mov ss,ax
mov sp,offset stack
mov dx,offset signon
call pstr
call setup ;get disk stuff
jnc st1
call pstr
int 32 ;error.
st1: call liststat ;describe dsk
mov dx,offset contstr
call pstr ;type any key..
call ina
;
;Find all the bad blocks, if any, display them,
;ask if we should update the FAT. If so, write
;it out.
;
mov dx,offset crlf
call pstr
call findbad ;map bad,
call listbad ;list them,
cmp newbad,0 ;if new bad
je st2 ;blocks...
st1a: mov dx,offset updstr ;ask if we
call pstr ;should update
call ina
and al,5fh
cmp al,'N'
je st2
cmp al,'Y'
jne st1a
mov al,disk ;write out the
mov dx,fatsec ;FAT,
mov cx,fatcnt
mov bx,offset fatbuf
int 26h
pop ax ;pop flags
st2: mov al,curdsk ;reselect the
call seldsk ;original disk
int 32
signon db cr,lf,'DOS version 2, 3 Bad Sector Mapper'
db cr,lf,'T. Jennings 12 July 85'
db cr,lf,' Reads all blocks on the disk, and marks'
db cr,lf,' unused bad ones in the FAT so that MSDOS'
db cr,lf,' will not use them later. It will not touch'
db cr,lf,' files with bad blocks; COPY the file to'
db cr,lf,' save what you can, DELete it, then run'
db cr,lf,' SCAVENGE to map out the bad block.'
db '$'
contstr db cr,lf,'Type ^C to abort, any '
db 'other key to continue: $'
updstr db cr,lf,lf,' Want the disk updated? [y,n] :$'
crlf db cr,lf,'$'
page
;
;Get the data on the specified disk. Return
;carry if no drive specified. Returns ES:DI
;pointing to the FAT for the selected drive.
;
setup: mov dx,offset wtstr
call pstr
call initdsk ;reset dsk sys,
call getdsk ;get current,
mov curdsk,al ;save it,
mov al,tfcb ;make sure a
cmp al,0 ;new one spec'd
stc ;quit if none,
mov dx,offset strstr
jz gd1
dec al ;make 0-N,
mov disk,al
call seldsk ;select,
push ds ;save local DS,
mov ah,1bh
int 33
pop ds
mov blkcnt,dx ;save # blocks,
mov secsize,cx ;sector size,
mov ah,0
mov blksize,ax ;secs/block.
mov fat16,0 ;assume small
cmp blkcnt,4085 ;FAT then check
jb gd0 ;for large
mov fat16,1
gd0: push ds ;now get the
mov dl,disk
inc dl ;drive 1=A, b=2
mov ah,50 ;FAT,
int 33 ;get the DPB,
mov cx,[bx+15] ;CX= sec count,
mov ch,0
mov dx,[bx+6] ;DX= 1st sec,
pop ds
mov fatcnt,cx ;save both,
mov fatsec,dx
mov al,disk ;AL= drive #,
mov bx,offset fatbuf ;DS:BX= buffer
int 25h ;read the FAT,
pop ax ;pop flags
mov dx,offset bscstr
gd1: ret
wtstr db cr,lf,lf,'Wait ...$'
strstr db cr,lf,'Must specify a disk drive.$'
bscstr db cr,lf,'Bad FAT sector: disk not useable.$'
page
;
;Read the entire disk looking for bad blocks.
;When one is found, go mark it as an allocated
;bad block.
;
findbad:
mov block,0 ;1st block,
mov badcnt,0 ;none yet,
mov blkdsp,1
fb1: dec blkdsp ;every 10th
jnz fb1a ;block
mov blkdsp,10
mov dx,offset blkstr ;type 'block '
call pstr
mov bx,block ;block number,
call outdec
fb1a: call readblk ;read a block,
jnc fb3 ;if bad,
inc badcnt ;count it,
mov dx,offset blkstr ;type 'block '
call pstr
mov bx,block ;block number,
call outdec
mov dx,offset badstr
call pstr ;type 'bad'
call mapout ;mark bad,
mov dx,offset cntstr ;error if cant
jc fb2
add newbad,cx ;count it,
mov dx,offset alrstr
jcxz fb2 ;already markd
mov dx,offset mrkstr
fb2: call pstr
fb3: inc block ;next block,
dec blkcnt ;another...
jnz fb1 ;keep looking.
ret
blkstr db cr,'Block $'
badstr db ' bad,$'
alrstr db ' already marked.',lf,'$'
mrkstr db ' mapped out.',lf,'$'
cntstr db ' already used! I dont know'
db ' which file.',lf,'$'
page
;
;Map out the bad block. For a 16 bit FAT, its
;easy.
;
mapout: test fat16,1
jz mo0
mov bx,block
shl bx,1 ;times 2,
mov ax,fatbuf[bx] ;read fat ptr
;
;AX is the block number; if it's anything
;but 0000 or fff7, return with carry set,
;indicating that its already used.
;
mov cx,0 ;none mapped
cmp ax,0fff7h ;if fff7,
je ml2 ;already marked
cmp ax,0
stc
jnz ml2 ;allocated
mov word ptr fatbuf[bx],0fff7h
add cx,1 ;(clr carry)
ml2: ret
;
;Mark the current block as bad in the FAT.
;Multiply the block number by 1.5 to find the
;block number, (actually *3, /2) and if not
;used, mark it bad. If used, report which file
;it's in. If it's already mapped as bad,
;return CX =0, else return CX=1.
;
mo0: mov bx,block ;block,
shl bx,1 ;times 2,
add bx,block ;times 3,
shr bx,1 ;divide by 2,
mov ax,fatbuf[bx] ;get word,
;
;If carry is set, we want the high 12 bits in
;the word in AX, else the low 12 bits. Set CH
;as the shift count, DX as the mask.
;
mov ch,0 ;assume low,
mov dx,0fffh
jnc mo1
mov ch,4 ;else high 12,
mov dx,0fff0h
mo1: and ax,dx ;mask it,
mov cl,ch
shr ax,cl ;shift it,
;
;AX is the block number; if it's anything
;but 000 or ff7, return with carry set,
;indicating that its already used.
;
cmp ax,0ff7h ;if ff7,
je mo2 ;already marked
cmp ax,0 ;if allocated,
je mo3
stc ;error!
mo2: mov cx,0 ;none mapped,
ret
;
;Bad unused block. Mark as bad in the FAT.
;
mo3: mov ax,0ff7h ;marker,
mov cl,ch
shl ax,cl ;shift it,
or fatbuf[bx],ax ;mark it.
mov cx,1 ;1 mapped,
ret
page
;
;Read one block, return carry set if read
;error. Leave the useless data in the buffer
;following the end of this program.
;
readblk:
mov ax,block ;find start
mov cx,blksize ;sector,
mul cx ;CX= count,
mov dx,ax ;DX= sector,
mov al,disk
mov bx,offset blkbuf ;our buffer,
int 25h ;read sectors,
pop dx ;pop flags,
ret
page
;
;List the general info on the disk, like
;sector sizes, etc.
;
liststat:
mov dx,offset st1str
call pstr
mov al,disk
add al,'A'
call outa
mov dx,offset st2str
call pstr
mov bx,blkcnt
call outdec
mov dx,offset st3str
call pstr
mov dx,offset st4astr
test fat16,1
jz ls1
mov dx,offset st4bstr
ls1: call pstr
ret
;Disk A:, total of 12345 data blocks.
st1str db cr,lf,'Disk $'
st2str db ':, total of $'
st3str db ' data blocks, $'
st4astr db '12 bit FAT.$'
st4bstr db '16 bit FAT.$'
;
;List out the bad things about this disk.
;
listbad:
mov dx,offset bd1str
call pstr
mov bx,badcnt
call outdec
mov dx,offset bd2str
call pstr
mov bx,newbad
call outdec
mov dx,offset bd3str
call pstr
ret
;Total of 12345 bad blocks, found 12234 more this pass.
bd1str db cr,'Total of $' ;note no linefeed.
bd2str db ' bad blocks, found $'
bd3str db ' more this pass.$'
page
;
;Generally useful system calls.
;
pstr: mov ah,9
int 33
ret
;
;Type BX in decimal, suppressing leading
;zeros.
;
outdec: mov cl,0 ;0 suppress flag,
mov dx,10000
call rsdiv
mov dx,1000
call rsdiv
mov dx,100
call rsdiv
mov dx,10
call rsdiv
mov ch,bl
jmp odf
rsdiv: mov ch,-1 ;iteration -1,
rs1: inc ch ;count,
sub bx,dx ;subtract,
jnc rs1 ;til underflow,
add bx,dx ;adjust back,
cmp ch,0 ;if non-zero,
jne odf ;type it,
test cl,1 ;dont type 0's
jnz odf ;if leading,
ret
odf: push dx
mov dl,ch
add dl,'0' ;ASCII,
mov ah,2
int 33
pop dx
mov cl,1 ;no suppress,
ret
page
;
;More system calls.
;
seldsk: mov dl,al ;select disk,
mov ah,0eh
int 33
ret
getdsk: mov ah,19h
int 33
ret
initdsk:mov ah,0dh
int 33
ret
ina: mov ah,0ch ;char in with
mov al,1 ;flush.
int 33
ret
outa: mov dl,al
mov ah,2
int 33
ret
blkbuf db 16384 dup (?) ;cluster buffer
fatbuf label word ;FAT buffer.
code ends
end scavenge